"""
设备资产管理模块回归测试脚本
自动化验证所有功能，确保模块稳定性和完整性
"""

import sys
import os
import logging
import time
import uuid
from datetime import datetime

# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class AssetRegressionTest:
    """设备资产管理模块回归测试类"""
    
    def __init__(self):
        self.test_results = []
        self.start_time = time.time()
        self.asset_service = None
        self.test_assets = []  # 存储测试创建的资产ID，用于清理
        
    def log_test_result(self, test_name, success, message="", duration=0):
        """记录测试结果"""
        result = {
            'test_name': test_name,
            'success': success,
            'message': message,
            'duration': duration,
            'timestamp': datetime.now().isoformat()
        }
        self.test_results.append(result)
        
        status = "✅ PASS" if success else "❌ FAIL"
        print(f"{status} {test_name} ({duration:.3f}s)")
        if message:
            print(f"    {message}")
    
    def setup(self):
        """测试环境初始化"""
        try:
            from src.app.modules.asset.service import AssetService
            from src.app.modules.asset.utils import AssetUtils
            from src.app.modules.asset.cache import AssetCache
            
            self.asset_service = AssetService()
            self.asset_utils = AssetUtils()
            self.asset_cache = AssetCache()
            
            print("🔧 测试环境初始化完成")
            return True
        except Exception as e:
            print(f"❌ 测试环境初始化失败: {e}")
            return False
    
    def cleanup(self):
        """测试环境清理"""
        try:
            # 清理测试创建的资产
            if self.asset_service and self.test_assets:
                print(f"\n🧹 清理测试数据，共 {len(self.test_assets)} 个资产...")
                for asset_id in self.test_assets:
                    try:
                        self.asset_service.delete_asset(asset_id)
                    except Exception as e:
                        logger.warning(f"清理资产 {asset_id} 失败: {e}")
                
                # 清除缓存
                self.asset_service.clear_cache()
                print("✅ 测试数据清理完成")
        except Exception as e:
            logger.error(f"清理测试环境失败: {e}")
    
    def test_utils_functions(self):
        """测试工具类函数"""
        print("\n📋 测试工具类函数...")
        
        # 测试生成资产ID
        start_time = time.time()
        try:
            asset_id = self.asset_utils.generate_asset_id()
            success = asset_id.startswith("AST_") and len(asset_id) == 12
            self.log_test_result(
                "生成资产ID", 
                success, 
                f"生成的ID: {asset_id}" if success else "ID格式不正确",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("生成资产ID", False, str(e), time.time() - start_time)
        
        # 测试数据验证
        start_time = time.time()
        try:
            valid_data = {
                'asset_type': 'server',
                'asset_name': '测试服务器',
                'asset_code': f'TEST_{uuid.uuid4().hex[:8]}',
                'cpu_cores': 8,
                'memory_gb': 16.0
            }
            is_valid, error_msg = self.asset_utils.validate_asset_data(valid_data)
            self.log_test_result(
                "有效数据验证", 
                is_valid, 
                error_msg if not is_valid else "验证通过",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("有效数据验证", False, str(e), time.time() - start_time)
        
        # 测试无效数据验证
        start_time = time.time()
        try:
            invalid_data = {
                'asset_name': '测试服务器',
                # 缺少必填字段
            }
            is_valid, error_msg = self.asset_utils.validate_asset_data(invalid_data)
            self.log_test_result(
                "无效数据验证", 
                not is_valid, 
                f"正确拒绝无效数据: {error_msg}" if not is_valid else "未能识别无效数据",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("无效数据验证", False, str(e), time.time() - start_time)
        
        # 测试设备组成关系解析
        start_time = time.time()
        try:
            composition_str = '["AST_001", "AST_002", "AST_003"]'
            result = self.asset_utils.parse_device_composition(composition_str)
            success = result == ["AST_001", "AST_002", "AST_003"]
            self.log_test_result(
                "设备组成关系解析", 
                success, 
                f"解析结果: {result}" if success else "解析失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("设备组成关系解析", False, str(e), time.time() - start_time)
        
        # 测试设备组成关系格式化
        start_time = time.time()
        try:
            asset_ids = ["AST_001", "AST_002", "AST_003"]
            result = self.asset_utils.format_device_composition(asset_ids)
            expected = '["AST_001", "AST_002", "AST_003"]'
            success = result == expected
            self.log_test_result(
                "设备组成关系格式化", 
                success, 
                f"格式化结果: {result}" if success else "格式化失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("设备组成关系格式化", False, str(e), time.time() - start_time)
    
    def test_cache_functions(self):
        """测试缓存功能"""
        print("\n💾 测试缓存功能...")
        
        # 测试缓存设置和获取
        start_time = time.time()
        try:
            test_key = "test_key"
            test_data = {"test": "data", "number": 123}
            
            self.asset_cache._set_cache(test_key, test_data)
            result = self.asset_cache._get_cache(test_key)
            success = result == test_data
            self.log_test_result(
                "缓存设置和获取", 
                success, 
                "缓存数据一致" if success else "缓存数据不一致",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("缓存设置和获取", False, str(e), time.time() - start_time)
        
        # 测试缓存过期
        start_time = time.time()
        try:
            original_ttl = self.asset_cache._cache_ttl
            self.asset_cache._cache_ttl = 0.001  # 1毫秒
            
            test_key = "expire_test"
            test_data = {"expire": "test"}
            self.asset_cache._set_cache(test_key, test_data)
            
            time.sleep(0.002)  # 等待过期
            result = self.asset_cache._get_cache(test_key)
            success = result is None
            
            # 恢复原始TTL
            self.asset_cache._cache_ttl = original_ttl
            
            self.log_test_result(
                "缓存过期", 
                success, 
                "缓存正确过期" if success else "缓存未过期",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("缓存过期", False, str(e), time.time() - start_time)
        
        # 测试缓存清除
        start_time = time.time()
        try:
            self.asset_cache._set_cache("clear_test1", "data1")
            self.asset_cache._set_cache("clear_test2", "data2")
            
            self.asset_cache.clear_cache()
            
            result1 = self.asset_cache._get_cache("clear_test1")
            result2 = self.asset_cache._get_cache("clear_test2")
            success = result1 is None and result2 is None
            
            self.log_test_result(
                "缓存清除", 
                success, 
                "缓存已清除" if success else "缓存清除失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("缓存清除", False, str(e), time.time() - start_time)
        
        # 测试缓存信息获取
        start_time = time.time()
        try:
            self.asset_cache._set_cache("info_test", "data")
            info = self.asset_cache.get_cache_info()
            success = isinstance(info, dict) and 'total_items' in info
            self.log_test_result(
                "缓存信息获取", 
                success, 
                f"缓存项目数: {info.get('total_items', 0)}" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("缓存信息获取", False, str(e), time.time() - start_time)
    
    def test_service_crud(self):
        """测试服务层CRUD操作"""
        print("\n🏢 测试服务层CRUD操作...")
        
        # 测试创建资产
        start_time = time.time()
        asset_id = None
        try:
            asset_data = {
                'asset_type': 'server',
                'asset_name': '回归测试服务器',
                'asset_code': f'REGRESS_{uuid.uuid4().hex[:8]}',
                'model': 'Test Model',
                'cpu_cores': 4,
                'memory_gb': 8.0,
                'storage_capacity': 500.0,
                'hard_disk_count': 2,
                'hard_disk_specs': '250GB SSD',
                'department': '测试部门',
                'purpose_desc': '回归测试用途'
            }
            
            result = self.asset_service.create_asset(asset_data)
            success = result['success']
            if success:
                asset_id = result['data']['asset_id']
                self.test_assets.append(asset_id)  # 记录用于清理
            
            self.log_test_result(
                "创建资产", 
                success, 
                f"资产ID: {asset_id}" if success else result['message'],
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("创建资产", False, str(e), time.time() - start_time)
        
        if not asset_id:
            print("❌ 资产创建失败，跳过后续CRUD测试")
            return
        
        # 测试获取单个资产
        start_time = time.time()
        try:
            asset = self.asset_service.get_asset_by_id(asset_id)
            success = asset is not None and asset['asset_name'] == '回归测试服务器'
            self.log_test_result(
                "获取单个资产", 
                success, 
                f"资产名称: {asset['asset_name'] if asset else 'None'}" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("获取单个资产", False, str(e), time.time() - start_time)
        
        # 测试更新资产
        start_time = time.time()
        try:
            update_data = {
                'asset_name': '回归测试服务器-已更新',
                'cpu_cores': 8,
                'memory_gb': 16.0
            }
            
            result = self.asset_service.update_asset(asset_id, update_data)
            success = result['success']
            self.log_test_result(
                "更新资产", 
                success, 
                result['message'] if success else result['message'],
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("更新资产", False, str(e), time.time() - start_time)
        
        # 测试获取所有资产
        start_time = time.time()
        try:
            assets = self.asset_service.get_all_assets()
            success = isinstance(assets, list) and len(assets) >= 0
            self.log_test_result(
                "获取所有资产", 
                success, 
                f"资产数量: {len(assets)}" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("获取所有资产", False, str(e), time.time() - start_time)
        
        # 测试资产筛选
        start_time = time.time()
        try:
            filters = {'asset_type': 'server', 'department': '测试部门'}
            filtered_assets = self.asset_service.get_all_assets(filters)
            success = isinstance(filtered_assets, list)
            self.log_test_result(
                "资产筛选", 
                success, 
                f"筛选结果: {len(filtered_assets)} 个资产" if success else "筛选失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("资产筛选", False, str(e), time.time() - start_time)
        
        # 测试资产统计
        start_time = time.time()
        try:
            stats = self.asset_service.get_asset_statistics()
            success = isinstance(stats, dict) and 'total_count' in stats
            self.log_test_result(
                "资产统计", 
                success, 
                f"总资产数: {stats.get('total_count', 0)}" if success else "统计失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("资产统计", False, str(e), time.time() - start_time)
    
    def test_service_advanced(self):
        """测试服务层高级功能"""
        print("\n🔧 测试服务层高级功能...")
        
        # 测试获取资产类型
        start_time = time.time()
        try:
            asset_types = self.asset_service.get_asset_types()
            success = isinstance(asset_types, list)
            self.log_test_result(
                "获取资产类型", 
                success, 
                f"类型数量: {len(asset_types)}" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("获取资产类型", False, str(e), time.time() - start_time)
        
        # 测试获取部门列表
        start_time = time.time()
        try:
            departments = self.asset_service.get_departments()
            success = isinstance(departments, list)
            self.log_test_result(
                "获取部门列表", 
                success, 
                f"部门数量: {len(departments)}" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("获取部门列表", False, str(e), time.time() - start_time)
        
        # 测试数据导出
        start_time = time.time()
        try:
            export_data = self.asset_service.export_assets()
            success = isinstance(export_data, list)
            self.log_test_result(
                "数据导出", 
                success, 
                f"导出数据量: {len(export_data)} 条" if success else "导出失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("数据导出", False, str(e), time.time() - start_time)
        
        # 测试缓存信息
        start_time = time.time()
        try:
            cache_info = self.asset_service.get_cache_info()
            success = isinstance(cache_info, dict) and 'total_items' in cache_info
            self.log_test_result(
                "获取缓存信息", 
                success, 
                f"缓存项目: {cache_info.get('total_items', 0)} 个" if success else "获取失败",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("获取缓存信息", False, str(e), time.time() - start_time)
    
    def test_error_handling(self):
        """测试错误处理"""
        print("\n⚠️ 测试错误处理...")
        
        # 测试创建重复资产编码
        start_time = time.time()
        try:
            if self.test_assets:
                # 获取第一个测试资产的编码
                first_asset = self.asset_service.get_asset_by_id(self.test_assets[0])
                if first_asset:
                    duplicate_data = {
                        'asset_type': 'server',
                        'asset_name': '重复编码测试',
                        'asset_code': first_asset['asset_code']  # 使用重复编码
                    }
                    
                    result = self.asset_service.create_asset(duplicate_data)
                    success = not result['success'] and "已存在" in result['message']
                    self.log_test_result(
                        "重复编码错误处理", 
                        success, 
                        result['message'] if not result['success'] else "未能检测到重复编码",
                        time.time() - start_time
                    )
                else:
                    self.log_test_result("重复编码错误处理", False, "无法获取测试资产", time.time() - start_time)
            else:
                self.log_test_result("重复编码错误处理", False, "没有测试资产", time.time() - start_time)
        except Exception as e:
            self.log_test_result("重复编码错误处理", False, str(e), time.time() - start_time)
        
        # 测试删除不存在的资产
        start_time = time.time()
        try:
            result = self.asset_service.delete_asset("NON_EXISTENT_ID")
            success = not result['success']
            self.log_test_result(
                "删除不存在资产错误处理", 
                success, 
                result['message'] if not result['success'] else "未能检测到不存在的资产",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("删除不存在资产错误处理", False, str(e), time.time() - start_time)
        
        # 测试更新不存在的资产
        start_time = time.time()
        try:
            update_data = {'asset_name': '测试更新'}
            result = self.asset_service.update_asset("NON_EXISTENT_ID", update_data)
            success = not result['success']
            self.log_test_result(
                "更新不存在资产错误处理", 
                success, 
                result['message'] if not result['success'] else "未能检测到不存在的资产",
                time.time() - start_time
            )
        except Exception as e:
            self.log_test_result("更新不存在资产错误处理", False, str(e), time.time() - start_time)
    
    def generate_report(self):
        """生成测试报告"""
        total_tests = len(self.test_results)
        passed_tests = sum(1 for result in self.test_results if result['success'])
        failed_tests = total_tests - passed_tests
        total_duration = time.time() - self.start_time
        
        print("\n" + "="*60)
        print("📊 设备资产管理模块回归测试报告")
        print("="*60)
        print(f"测试开始时间: {datetime.fromtimestamp(self.start_time).strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"测试结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"总测试时间: {total_duration:.3f} 秒")
        print(f"总测试数量: {total_tests}")
        print(f"通过测试数量: {passed_tests}")
        print(f"失败测试数量: {failed_tests}")
        print(f"测试通过率: {(passed_tests/total_tests*100):.1f}%")
        
        if failed_tests > 0:
            print("\n❌ 失败的测试:")
            for result in self.test_results:
                if not result['success']:
                    print(f"  - {result['test_name']}: {result['message']}")
        
        print("\n📋 详细测试结果:")
        for result in self.test_results:
            status = "✅ PASS" if result['success'] else "❌ FAIL"
            print(f"  {status} {result['test_name']} ({result['duration']:.3f}s)")
        
        print("\n" + "="*60)
        
        return failed_tests == 0
    
    def run_all_tests(self):
        """运行所有测试"""
        print("🚀 开始设备资产管理模块回归测试...")
        print("="*60)
        
        # 初始化测试环境
        if not self.setup():
            return False
        
        try:
            # 运行各类测试
            self.test_utils_functions()
            self.test_cache_functions()
            self.test_service_crud()
            self.test_service_advanced()
            self.test_error_handling()
            
            # 生成报告
            success = self.generate_report()
            
            return success
            
        finally:
            # 清理测试环境
            self.cleanup()

def main():
    """主函数"""
    try:
        test_runner = AssetRegressionTest()
        success = test_runner.run_all_tests()
        
        if success:
            print("\n🎉 所有回归测试通过！设备资产管理模块功能正常。")
            return 0
        else:
            print("\n❌ 部分回归测试失败，请检查相关功能。")
            return 1
    except Exception as e:
        print(f"\n💥 回归测试执行失败: {e}")
        import traceback
        traceback.print_exc()
        return 1

if __name__ == '__main__':
    sys.exit(main())
